#include "header/pyramid_stdinc.h"


#include "header/pyramid_body.h"
#include "header/pyramid_entrance.h"
#include "header/pyramid_roompass.h"
#include "header/pyramid_room1.h"
#include "header/pyramid_room2.h"
#include "header/pyramid_lights.h"
#include "header/pyramid_walkerscene.h"
#include "header/pyramid_room1_objects.h"
#include "header/pyramid_room2_objects.h"
#include "header/pyramid_entrance_objects.h"
#include "header/pyramid_roompass_objects.h"
#include "header/pyramid_particles.h"


#if defined(WIN32) || defined(__WATCOMC__)
#include <conio.h>
#include <windows.h>
#elif defined(__linux__)
#include "fmod/includes/wincompat.h"
#endif
#include "fmod/includes/fmod.h"
#include "fmod/includes/fmod_errors.h"

#define DEG2RAD(x) x * M_PI/180
#define N 50

OSG_USING_NAMESPACE

// please leave local debug switch
//#define DEBUG

//#define USE_OLD_SHADOWS

#define SHADOWS

SimpleSceneManager *mgr;
NodePtr visible_scene;
NodePtr walker_scene;
NodePtr scene;
int brake;
int mousex,mousey;

// door motion variables
bool dooropen=false;
bool doormoving=false;
int doorposition=0;

// stargate animation
bool stargate_evolving;
float evolution_counter;

// mouseover variables
bool door_hover;
bool coffin_hover;

// shadow toggle
bool shadows_on=true;

// animation oscillator
int osc=0;

Real32 iris_mesh[N][N];

NodePtr roompassTrans;

// particle-system variables
GeoPositions3fPtr pnts, secpnts, tmpPnts;
MFVec3f *size;
GeoColors3fPtr cols, tmpColors;
// data vectors for particle-system
vector<double> lifeSpanList;
vector<Vec3d> startVec3dList;
vector<Vec3d> targetVec3dList;

Real32 speed = 2.0;

// Global Sounds

FSOUND_SAMPLE *bgmusic = 0, *tardis_landing=0, *door_movement=0, *gate_opening=0;

// forward declarations
int setupGLUT( int *argc, char *argv[] );
NodePtr createScenegraph();
double dRand(double);
TextureChunkPtr createTexture( std::string filename );
Action::ResultE enter(NodePtr& node);
NodePtr getNamedNode(NodePtr n, std::string name);

#ifdef USE_OLD_SHADOWS
ShadowMapViewportPtr svp;
#else
ShadowViewportPtr svp;
#endif

int initSound()
{
//select output driver
	printf("---------------------------------------------------------\n");    
	printf("Wookies CG1 Project - Pyramid\n");    
	printf("---------------------------------------------------------\n");
	printf("Select Sound Device:\n");    
	printf("---------------------------------------------------------\n");
#if defined(WIN32) || defined(__CYGWIN32__) || defined(__WATCOMC__)
	printf("1 - Direct Sound\n");
	printf("2 - Windows Multimedia Waveout\n");
	printf("3 - ASIO\n");
#elif defined(__linux__)
	printf("1 - OSS - Open Sound System\n");
	printf("2 - ESD - Elightment Sound Daemon\n");
	printf("3 - ALSA 0.9 - Advanced Linux Sound Architecture\n");   
#endif
	printf("4 - NoSound\n");
	printf("  \n");
	cout << "-->" << endl;

	int key;

	do
	{
		key = getch();
	} while (key != 27 && key < '1' && key > '4');

	switch (key)
	{
#if defined(WIN32) || defined(__CYGWIN32__) || defined(__WATCOMC__)
		case '1' :  FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
		break;
		case '2' :  FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
		break;
		case '3' :  FSOUND_SetOutput(FSOUND_OUTPUT_ASIO);
		break;
#elif defined(__linux__)
		case '1' :  FSOUND_SetOutput(FSOUND_OUTPUT_OSS);
		break;
		case '2' :  FSOUND_SetOutput(FSOUND_OUTPUT_ESD);
		break;
		case '3' :  FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
		break;
#endif        
		case '4' :  FSOUND_SetOutput(FSOUND_OUTPUT_NOSOUND);
		break;       
       
		default :   return 1;
	}
//FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
	printf("\n");   
	printf("\n");   
	printf("SOUND--------------------------------------------------->\n");
	printf("\n");
	printf("initializing sound driver");

//check for correct FMOD version
	if (FSOUND_GetVersion() < FMOD_VERSION)
	{
		printf("Error : You are using the wrong DLL version!  You should be using FMOD %.02f\n", FMOD_VERSION);
		exit(1);
	}
//hardcode ALSA - do we want this to be choosable?
//	FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
//initialize ALSA
	if (!FSOUND_Init(22000, 64, 0))
	{
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		exit(1);
	}

//load samples to soundbuffer and recheck integrity
//background music
	bgmusic = FSOUND_Sample_Load(FSOUND_UNMANAGED, "sounds/background.mp3", FSOUND_NORMAL, 0, 0);
	if (!bgmusic)
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		return 1;
	}
//tardis landing
	tardis_landing = FSOUND_Sample_Load(FSOUND_UNMANAGED, "sounds/tardis_landing.wav", FSOUND_NORMAL, 0, 0);
	if (!tardis_landing)
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		return 1;
	}
//stone door
	door_movement = FSOUND_Sample_Load(FSOUND_UNMANAGED, "sounds/door2.mp3", FSOUND_NORMAL, 0, 0);
	if (!door_movement)
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		return 1;
	}

//stone door
	gate_opening = FSOUND_Sample_Load(FSOUND_UNMANAGED, "sounds/gate_opening.mp3", FSOUND_NORMAL, 0, 0);
	if (!gate_opening)
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		return 1;
	}

	printf("............................done\n");
	printf("\n");

//set sample parameters
	FSOUND_SetSFXMasterVolume(200);
	FSOUND_SetVolumeAbsolute(1,150);
	FSOUND_SetVolumeAbsolute(2,255);
	FSOUND_SetVolumeAbsolute(3,150);
	printf("Channel Volumes:\n");
	cout << "Channel 1:"<< FSOUND_GetVolume(1) << endl;;
	cout << "Channel 2:"<< FSOUND_GetVolume(2) << endl;;
	cout << "Channel 3:"<< FSOUND_GetVolume(3) << endl;;
	FSOUND_SetLoopMode(1,FSOUND_LOOP_NORMAL);
	FSOUND_Sample_SetMode(bgmusic,FSOUND_LOOP_NORMAL);

	printf("\n");
	printf("Volume settings......................................done\n");
	printf("\n");

	printf("SCENE--------------------------------------------------->\n");
	printf("\n");
 
}

int main(int argc, char **argv)
{	
	initSound();

	osgInit(argc,argv);

	int windowID = setupGLUT(&argc, argv);
	GLUTWindowPtr gwin= GLUTWindow::create();
	gwin->setId(windowID);
	gwin->init();

	SkyBackgroundPtr sky = SkyBackground::create();
	mgr = new SimpleSceneManager;
	// create object-scene
	visible_scene = createScenegraph();
	// create collision-scene
	walker_scene  = createWalkerScene();
	
	// create rootNode
	scene = Node::create();
	
	
	beginEditCP(scene);
	scene->setCore(Group::create());
	scene->addChild(visible_scene);
	scene->addChild(walker_scene);
	endEditCP(scene);
	
#ifdef USE_OLD_SHADOWS
	svp = ShadowMapViewport::create();
#else
	svp = ShadowViewport::create();
#endif
	printf("scene preparation....................................done\n");
	printf("\n");
	printf("SYSTEM-------------------------------------------------->\n");
	printf("\n");
	printf("skybox construction");

// SkyBox construction

	beginEditCP(sky);
	sky->setSphereRes(512);
	sky->getMFSkyColor()->push_back(Color4f(0, 0, 1, 0.5));
	sky->getMFSkyAngle()->push_back(M_PI / 4);
	sky->getMFSkyColor()->push_back(Color4f(0, 1, 0, 0.5));
	sky->getMFSkyAngle()->push_back(M_PI / 2);
	sky->getMFSkyColor()->push_back(Color4f(1, 0, 0, 0.5));
	sky->getMFGroundColor()->push_back(Color4f(0, 1, 1, 0.5));
	sky->getMFGroundAngle()->push_back(M_PI / 8);
	sky->getMFGroundColor()->push_back(Color4f(1, 0, 1, 0.5));
	sky->getMFGroundAngle()->push_back(M_PI / 4);
	sky->getMFGroundColor()->push_back(Color4f(1, 1, 1, 0.5));

	sky->setBackTexture  (
			      createTexture("materials/pos_z.bmp") );
	sky->setFrontTexture (
			      createTexture("materials/neg_z.bmp") );
	sky->setLeftTexture  (
			      createTexture("materials/pos_x.bmp") );
	sky->setRightTexture (
			      createTexture("materials/neg_x.bmp") );
	sky->setBottomTexture(
			      createTexture("materials/neg_y.bmp") );
	sky->setTopTexture   (
			      createTexture("materials/pos_y.bmp") );
	endEditCP(sky);

	printf("..................................done\n");
	printf("generating shadow viewport");

// get Light Nodes

	NodePtr svpCryptLight1 = getNamedNode(scene,"cryptLight1");
	NodePtr svpCryptLight2 = getNamedNode(scene,"cryptLight2");
	//NodePtr svpCryptLight3 = getNamedNode(scene,"cryptLight3");		// out of service
	//NodePtr svpCryptLight4 = getNamedNode(scene,"cryptLight4");		// out of service
	NodePtr svpEntranceLight1 = getNamedNode(scene,"entranceLight1");
	//NodePtr svpEntranceLight2 = getNamedNode(scene,"entranceLight2");	// out of service
	//NodePtr svpRoompassLight1 = getNamedNode(scene,"roompassLight1");	// out of service
	//NodePtr svpRoom2Light1 = getNamedNode(scene,"room2Light1");		// out of service
	//NodePtr svpRoom2Light2 = getNamedNode(scene,"room2Light2");		// out of service
	NodePtr svpRoom2BlueLight1 = getNamedNode(scene,"room2BlueLight1");
	NodePtr svpSunLight1 = getNamedNode(scene,"sunLight1");

// get nodes to exclude from shadowsystem
	NodePtr svpPyraBodyFront = getNamedNode(scene,"pyraBodyFront");
	NodePtr svpPyraBodyLeft = getNamedNode(scene,"pyraBodyLeft");
	NodePtr svpPyraBodyRight = getNamedNode(scene,"pyraBodyRight");
	NodePtr svpPyraBodyBack = getNamedNode(scene,"pyraBodyBack");
	NodePtr svpPyraBodyBottom = getNamedNode(scene,"pyraBodyBottom");
	NodePtr svpPyraBodyRoof = getNamedNode(scene,"pyraBodyRoof");
	
#ifdef ENTRANCE_PLANES_ON
	NodePtr svpEntranceLeftPass = getNamedNode(scene,"entranceLeftPass");
	NodePtr svpEntranceRightPass = getNamedNode(scene,"entranceRightPass");
	NodePtr svpEntranceLeftNode = getNamedNode(scene,"entranceLeftNode");
	NodePtr svpEntranceRightNode = getNamedNode(scene,"entranceRightNode");
	NodePtr svpEntranceBottom = getNamedNode(scene,"entranceBottom");
	NodePtr svpEntranceRoof = getNamedNode(scene,"entranceRoof");
#endif
	
#ifdef ROOM1_PLANES_ON
	NodePtr svpRoom1Left = getNamedNode(scene,"room1Left");
	NodePtr svpRoom1Right = getNamedNode(scene,"room1Right");
	NodePtr svpRoom1Front = getNamedNode(scene,"room1Front");
	NodePtr svpRoom1Back = getNamedNode(scene,"room1Back");
	NodePtr svpRoom1Bottom = getNamedNode(scene,"room1Bottom");
	NodePtr svpRoom1Roof = getNamedNode(scene,"room1Roof");
#endif
	
	NodePtr svpRoompassRoof = getNamedNode(scene,"roompassRoof");
	NodePtr svpRoompassBottom = getNamedNode(scene,"roompassBottom");
	NodePtr svpRoompassLeft = getNamedNode(scene,"roompassLeft");
	NodePtr svpRoompassRight = getNamedNode(scene,"roompassRight");
	
	NodePtr svpRoom2Roof = getNamedNode(scene,"room2Roof");
	NodePtr svpRoom2Bottom = getNamedNode(scene,"room2Bottom");
	NodePtr svpRoom2Left = getNamedNode(scene,"room2Left");
	NodePtr svpRoom2Right = getNamedNode(scene,"room2Right");
	NodePtr svpRoom2Back = getNamedNode(scene,"room2Back");
	NodePtr svpRoom2Front = getNamedNode(scene,"room2Front");
	
	NodePtr svpStargateIris = getNamedNode(scene,"stargate_iris");
	
    
#ifdef MOSAICS
	NodePtr Mosaic1 = getNamedNode(scene,"mosaic1");
	NodePtr Mosaic2 = getNamedNode(scene,"mosaic2");
	NodePtr Mosaic3 = getNamedNode(scene,"mosaic3");
	NodePtr Mosaic4 = getNamedNode(scene,"mosaic4");
#endif

#ifdef PARTICLES_ON
	NodePtr svpParticleSystem1 = getNamedNode(scene,"particleSystem1");
	NodePtr svpParticleSystem2 = getNamedNode(scene,"particleSystem2");
	NodePtr svpParticleSystem3 = getNamedNode(scene,"particleSystem3");
#endif
	

#ifdef USE_OLD_SHADOWS
	beginEditCP(svp);
	svp->setBackground(sky);
	svp->setRoot(scene);
	svp->setSize(0,0,1,1);
	svp->setOffFactor(10.0);
	svp->setOffBias(4.0);
	svp->setShadowColor(Color4f(0.1, 0.1, 0.1, 1.0));
	svp->setMapSize(512);
	svp->getLightNodes().push_back(svpCryptLight1);
	svp->getLightNodes().push_back(svpCryptLight2);
    
#ifdef MOSAICS
	svp->getExcludeNodes().push_back(Mosaic1);
#endif

#ifdef PARTICLES_ON
	svp->getExcludeNodes().push_back(Particles);
#endif 
    
    //svp->getExcludeNodes().push_back(rotaryBody);
    
    //svp->getExcludeNodes().push_back(roompassTrans);
	endEditCP(svp);
#else
    // Shadow viewport (new implementation)
	beginEditCP(svp);
	svp->setBackground(sky);
	svp->setRoot(scene);
	svp->setSize(0, 0, 1, 1);
	svp->setGlobalShadowIntensity(0.9);
	svp->setMapSize(1024);
	svp->setShadowMode(ShadowViewport::PCF_SHADOW_MAP);
    //svp->setShadowMode(ShadowViewport::STD_SHADOW_MAP);
	svp->setShadowSmoothness(0.3);
    // pushback all lightnodes
	svp->getLightNodes().push_back(svpCryptLight1);
	svp->getLightNodes().push_back(svpCryptLight2);
    //svp->getLightNodes().push_back(svpCryptLight3);		// out of service
    //svp->getLightNodes().push_back(svpCryptLight4);		// out of service
	svp->getLightNodes().push_back(svpEntranceLight1);
    //svp->getLightNodes().push_back(svpEntranceLight2);	// out of service
    //svp->getLightNodes().push_back(svpRoompassLight1);	// out of service
    //svp->getLightNodes().push_back(svpRoom2Light1);		// out of service
    //svp->getLightNodes().push_back(svpRoom2Light2);		// out of service
	svp->getLightNodes().push_back(svpRoom2BlueLight1);
	svp->getLightNodes().push_back(svpSunLight1);  
    
    
// pushback all excluded nodes
	// exclude pyra nodes
	svp->getExcludeNodes().push_back(svpPyraBodyFront);
	svp->getExcludeNodes().push_back(svpPyraBodyLeft);
	svp->getExcludeNodes().push_back(svpPyraBodyRight);
	svp->getExcludeNodes().push_back(svpPyraBodyBack);
	svp->getExcludeNodes().push_back(svpPyraBodyBottom);
	svp->getExcludeNodes().push_back(svpPyraBodyRoof);
    // exclude entrance wall nodes
#ifdef ENTRANCE_PLANES_ON
	svp->getExcludeNodes().push_back(svpEntranceLeftPass);
	svp->getExcludeNodes().push_back(svpEntranceRightPass);
	svp->getExcludeNodes().push_back(svpEntranceLeftNode);
	svp->getExcludeNodes().push_back(svpEntranceRightNode);
	svp->getExcludeNodes().push_back(svpEntranceRoof);
	svp->getExcludeNodes().push_back(svpEntranceBottom);
#endif
	// exclude room1 wall nodes
#ifdef ROOM1_PLANES_ON
	svp->getExcludeNodes().push_back(svpRoom1Left);
	svp->getExcludeNodes().push_back(svpRoom1Right);
	svp->getExcludeNodes().push_back(svpRoom1Front);
	svp->getExcludeNodes().push_back(svpRoom1Back);
	svp->getExcludeNodes().push_back(svpRoom1Bottom);
	svp->getExcludeNodes().push_back(svpRoom1Roof);
#endif
	// exclude roompass wall nodes
	svp->getExcludeNodes().push_back(svpRoompassBottom);
	svp->getExcludeNodes().push_back(svpRoompassRoof);
	svp->getExcludeNodes().push_back(svpRoompassLeft);
	svp->getExcludeNodes().push_back(svpRoompassRight);
	
	// exclude room2 wall nodes
	svp->getExcludeNodes().push_back(svpRoom2Bottom);
	svp->getExcludeNodes().push_back(svpRoom2Roof);
	svp->getExcludeNodes().push_back(svpRoom2Left);
	svp->getExcludeNodes().push_back(svpRoom2Right);
	svp->getExcludeNodes().push_back(svpRoom2Back);
	svp->getExcludeNodes().push_back(svpRoom2Front);
	
	// exclude stargate iris
	svp->getExcludeNodes().push_back(svpStargateIris);

#ifdef MOSAICS
	svp->getExcludeNodes().push_back(Mosaic1);
	svp->getExcludeNodes().push_back(Mosaic2);
	svp->getExcludeNodes().push_back(Mosaic3);
	svp->getExcludeNodes().push_back(Mosaic4);
#endif
    
#ifdef PARTICLES_ON
	svp->getExcludeNodes().push_back(svpParticleSystem1);
	svp->getExcludeNodes().push_back(svpParticleSystem2);
	svp->getExcludeNodes().push_back(svpParticleSystem3);
#endif 

 // pushback all excluded nodes
	svp->getExcludeNodes().push_back(svpPyraBodyFront);
    //svp->getExcludeNodes().push_back(svpPyraBodyLeft);
	svp->getExcludeNodes().push_back(svpPyraBodyRight);
    //svp->getExcludeNodes().push_back(svpPyraBodyBack);
    //svp->getExcludeNodes().push_back(svpPyraBodyBottom);
    //svp->getExcludeNodes().push_back(svpPyraBodyRoof);

    //svp->getExcludeNodes().push_back(rotaryBody1);
    //svp->getExcludeNodes().push_back(rotaryBody2);
    
    //svp->getExcludeNodes().push_back(roompassTrans);
    
    //svp->setMapAutoUpdate(true);
    //svp->setAutoSearchForLights(true);
	svp->setOffFactor(1.0);
	svp->setOffBias(4.0);
	endEditCP(svp);
#endif

	beginEditCP(gwin);//Window
	gwin->setId(windowID);
#ifdef SHADOWS
	gwin->addPort(svp);
#endif
	gwin->init();
	endEditCP(gwin);

	mgr->setWindow(gwin);
	mgr->setRoot(scene);

#ifndef SHADOWS
	mgr->getWindow()->getPort(0)->setBackground( sky );
#endif

	mgr->setNavigationMode(Navigator::FLY);
	mgr->setStatistics(true);

	beginEditCP(svp);
	svp->setCamera(mgr->getCamera());
	endEditCP(svp);

// set Occlusion Culling
	RenderAction *ract = (RenderAction *) mgr->getAction();
	ract->setOcclusionCulling(!ract->getOcclusionCulling());
	ract->setOcclusionCullingMode(RenderAction::OcclusionMultiFrame);

    	// enable local lights.
	ract->setLocalLights(true);
        
// Show the whole scene
    //mgr->showAll();

#ifdef ANY_LIGHT_IS_ON
    //shut off the default head light
	mgr->setHeadlight(false);    
#endif

	printf("...........................done\n");
	printf("initializing walker");

// initialize Navigation

	mgr->getNavigator()->set(Pnt3f(1250,150,2800),Pnt3f(1250,150,0),Vec3f(0,1,0));

	// testposition in room2
/*	mgr->getNavigator()->set(Pnt3f(790,150,1735),Pnt3f(400,150,1735),Vec3f(0,1,0));
	mgr->setNavigationMode(Navigator::FLY);*/
	
	mgr->getNavigator()->setMotionFactor(speed);
	
	mgr->setNavigationMode(Navigator::WALK);
	mgr->getNavigator()->getWalkNavigator()->setGroundDistance(1);
	mgr->getNavigator()->getWalkNavigator()->setMinWallDistance(10);
	mgr->getNavigator()->getWalkNavigator()->setPersonDimensions(50,20,20);
	mgr->getNavigator()->getWalkNavigator()->setUp(Vec3f(0,1,0));
	mgr->getNavigator()->getWalkNavigator()->setWorld(walker_scene);
	mgr->getNavigator()->getWalkNavigator()->setGround(walker_scene);
	
	
//play background music
	FSOUND_PlaySound(1,bgmusic);

	printf("..................................done\n");
	printf("\n");

	printf("---------------------------------------------------------\n");
	printf("\n");
	printf("ready...\n");
	printf("\n");

	glutMainLoop();

	return 0;
}

NodePtr createTerrain()
{
	/***************************************
	* load external objects
	* ************************************/
	
	Matrix m;
	
	cout << "--> parsing external object: terrain.wrl" << endl;
	NodePtr external_terrain = SceneFileHandler::the().read("external_objects/terrain.wrl");

	TransformPtr tterrain = Transform::create();
	beginEditCP(tterrain, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setScale(3);
	tterrain->setMatrix(m);
	endEditCP(tterrain, Transform::MatrixFieldMask);

	TransformPtr tterrain2 = Transform::create();
	beginEditCP(tterrain2, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(-400,-1610,-800);
	tterrain2->setMatrix(m);
	endEditCP(tterrain2, Transform::MatrixFieldMask);
	
	NodePtr terrainTrans1 = Node::create();
	beginEditCP(terrainTrans1, Node::CoreFieldMask | Node::ChildrenFieldMask);
	terrainTrans1->setCore(tterrain);
	terrainTrans1->addChild(external_terrain);
	endEditCP(terrainTrans1, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	NodePtr terrainTrans2 = Node::create();
	beginEditCP(terrainTrans2, Node::CoreFieldMask | Node::ChildrenFieldMask);
	terrainTrans2->setCore(tterrain2);
	terrainTrans2->addChild(terrainTrans1);
	endEditCP(terrainTrans2, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	return terrainTrans2;
}	


NodePtr createScenegraph(void)
{

// Multi Use Transformation Matrix
	Matrix m;
	
	/***************************************
	* Create a simple door element
	* ************************************/
	
	NodePtr simpleDoor = makeBox(70,90,10,1,1,1);
	TransformPtr tsimpleDoor = Transform::create();
	beginEditCP(tsimpleDoor, Transform::MatrixFieldMask);
	m.setIdentity();
		//m.setTranslate(20,50,350);
	m.setTranslate(-4,45,300);
	m.setRotate(Quaternion(Vec3f(0,1,0), -3.14159/2));
	tsimpleDoor->setMatrix(m);
	endEditCP(tsimpleDoor, Transform::MatrixFieldMask);

	NodePtr simpleDoorTrans = Node::create();
	beginEditCP(simpleDoorTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	simpleDoorTrans->setCore(tsimpleDoor);
	simpleDoorTrans->addChild(simpleDoor);
	endEditCP(simpleDoorTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	setName(simpleDoor,"simpleDoor");
	setName(simpleDoorTrans,"simpleDoorTrans");
	
	/***************************************
	* Create a door marker
	* ************************************/
	
	NodePtr simpleDoorMarkerTop = makeBox(72,2,2,30,30,10);
	TransformPtr tsimpleDoorMarkerTop = Transform::create();
	beginEditCP(tsimpleDoorMarkerTop, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0,90,300);
	m.setRotate(Quaternion(Vec3f(0,1,0), -3.14159/2));
	tsimpleDoorMarkerTop->setMatrix(m);
	endEditCP(tsimpleDoorMarkerTop, Transform::MatrixFieldMask);

	NodePtr simpleDoorMarkerTopTrans = Node::create();
	beginEditCP(simpleDoorMarkerTopTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	simpleDoorMarkerTopTrans->setCore(tsimpleDoorMarkerTop);
	simpleDoorMarkerTopTrans->addChild(simpleDoorMarkerTop);
	endEditCP(simpleDoorMarkerTopTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	NodePtr simpleDoorMarkerLeft = makeBox(2,90,2,1,1,1);
	TransformPtr tsimpleDoorMarkerLeft = Transform::create();
	beginEditCP(tsimpleDoorMarkerLeft, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0,45,265);
	m.setRotate(Quaternion(Vec3f(0,1,0), -3.14159/2));
	tsimpleDoorMarkerLeft->setMatrix(m);
	endEditCP(tsimpleDoorMarkerLeft, Transform::MatrixFieldMask);

	NodePtr simpleDoorMarkerLeftTrans = Node::create();
	beginEditCP(simpleDoorMarkerLeftTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	simpleDoorMarkerLeftTrans->setCore(tsimpleDoorMarkerLeft);
	simpleDoorMarkerLeftTrans->addChild(simpleDoorMarkerLeft);
	endEditCP(simpleDoorMarkerLeftTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	NodePtr simpleDoorMarkerRight = makeBox(2,90,2,1,1,1);
	TransformPtr tsimpleDoorMarkerRight = Transform::create();
	beginEditCP(tsimpleDoorMarkerRight, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0,45,335);
	m.setRotate(Quaternion(Vec3f(0,1,0), -3.14159/2));
	tsimpleDoorMarkerRight->setMatrix(m);
	endEditCP(tsimpleDoorMarkerRight, Transform::MatrixFieldMask);

	NodePtr simpleDoorMarkerRightTrans = Node::create();
	beginEditCP(simpleDoorMarkerRightTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	simpleDoorMarkerRightTrans->setCore(tsimpleDoorMarkerRight);
	simpleDoorMarkerRightTrans->addChild(simpleDoorMarkerRight);
	endEditCP(simpleDoorMarkerRightTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	SimpleMaterialPtr SimpleDoorMarkerMat = SimpleMaterial::create();
	beginEditCP(SimpleDoorMarkerMat); 
	SimpleDoorMarkerMat->setDiffuse(Color3f(1.0, 0.0, 0.0));
	SimpleDoorMarkerMat->setTransparency(0.4);
	endEditCP(SimpleDoorMarkerMat);

	GeometryPtr SimpleDoorMarkerGeo = GeometryPtr::dcast(simpleDoorMarkerTop->getCore());
	beginEditCP(SimpleDoorMarkerGeo);
	SimpleDoorMarkerGeo->setMaterial(SimpleDoorMarkerMat);
	endEditCP(SimpleDoorMarkerGeo);
	
	SimpleDoorMarkerGeo = GeometryPtr::dcast(simpleDoorMarkerLeft->getCore());
	beginEditCP(SimpleDoorMarkerGeo);
	SimpleDoorMarkerGeo->setMaterial(SimpleDoorMarkerMat);
	endEditCP(SimpleDoorMarkerGeo);
	
	SimpleDoorMarkerGeo = GeometryPtr::dcast(simpleDoorMarkerRight->getCore());
	beginEditCP(SimpleDoorMarkerGeo);
	SimpleDoorMarkerGeo->setMaterial(SimpleDoorMarkerMat);
	endEditCP(SimpleDoorMarkerGeo);

	
	NodePtr simpleDoorMarker = Node::create();
			
	beginEditCP(simpleDoorMarker);
	simpleDoorMarker->setCore(Group::create());
	simpleDoorMarker->addChild(simpleDoorMarkerTopTrans);
	simpleDoorMarker->addChild(simpleDoorMarkerLeftTrans);
	simpleDoorMarker->addChild(simpleDoorMarkerRightTrans);
	endEditCP(simpleDoorMarker);
	
	beginEditCP(simpleDoorMarker);
		//simpleDoorMarker->setActive(false);
	endEditCP(simpleDoorMarker);
	
	setName(simpleDoorMarker,"simpleDoorMarker");
	
	//Kammer Boden Texturen laden
	ImagePtr cryptWallImage = Image::create();
	cryptWallImage->read("materials/cryptWall.jpg");    
	    
	    
	//Aus dem Bild eine Textur machen
	TextureChunkPtr cryptWallTex = TextureChunk::create();
	beginEditCP(cryptWallTex);
	cryptWallTex->setImage(cryptWallImage);
	cryptWallTex->setMinFilter(GL_LINEAR);
	cryptWallTex->setMagFilter(GL_LINEAR);
	cryptWallTex->setWrapS(GL_REPEAT);
	cryptWallTex->setWrapT(GL_REPEAT);
	cryptWallTex->setEnvMode(GL_MODULATE);
	endEditCP(cryptWallTex);
	   
	SimpleMaterialPtr cryptWallMat = SimpleMaterial::create();
	beginEditCP(cryptWallMat); 
		//Materialfarbe bei seitlicher Ansicht (Brechungswinkel)
	cryptWallMat->setAmbient(Color3f(0.3, 0.3, 0.3));
		//Bestimmt Farbe des Materials
	cryptWallMat->setDiffuse(Color3f(1.0, 1.0, 1.0));
	cryptWallMat->setSpecular(Color3f(0.1, 0.1, 0.1));
	cryptWallMat->addChunk(cryptWallTex);
	endEditCP(cryptWallMat);

	
	GeometryPtr cryptWallGeo = GeometryPtr::dcast(simpleDoor->getCore());
	beginEditCP(cryptWallGeo);
	cryptWallGeo->setMaterial(cryptWallMat);
	endEditCP(cryptWallGeo);
	

	NodePtr entranceObjects = createEntranceObjects();
	
	// Transformation
	TransformPtr tentranceObjects = Transform::create();
	beginEditCP(tentranceObjects, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0, 0, 0);
	tentranceObjects->setMatrix(m);
	endEditCP(tentranceObjects, Transform::MatrixFieldMask);
		
	NodePtr entranceObjectsTrans = Node::create();
	beginEditCP(entranceObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	entranceObjectsTrans->setCore(tentranceObjects);
	entranceObjectsTrans->addChild(entranceObjects);
	endEditCP(entranceObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
#ifdef PARTICLES_ON
// **** create particel systems

	pnts = GeoPositions3f::create();
	cols = GeoColors3f::create();
	
	// particleSystem1
	NodePtr particleSystem1 = createParticleSystem();
	setName(particleSystem1, "particleSystem1");
	NodePtr particleSystem1Trans = Node::create();
	TransformPtr tparticleSystem1 = Transform::create();
	
	beginEditCP(tparticleSystem1);
	m.setIdentity();
	m.setTranslate(4.5, 48, 160);
	tparticleSystem1->setMatrix(m);
	endEditCP(tparticleSystem1);
    
	beginEditCP(particleSystem1Trans);
	particleSystem1Trans->setCore(tparticleSystem1);
	particleSystem1Trans->addChild(particleSystem1);
	endEditCP(particleSystem1Trans);

	// particleSystem2
	NodePtr particleSystem2 = createParticleSystem();
	setName(particleSystem2, "particleSystem2");
	NodePtr particleSystem2Trans = Node::create();
	TransformPtr tparticleSystem2 = Transform::create();
	
	beginEditCP(tparticleSystem2);
	m.setIdentity();
	m.setTranslate(245.5, 48, 160);
	tparticleSystem2->setMatrix(m);
	endEditCP(tparticleSystem2);
    
	beginEditCP(particleSystem2Trans);
	particleSystem2Trans->setCore(tparticleSystem2);
	particleSystem2Trans->addChild(particleSystem2);
	endEditCP(particleSystem2Trans);
    
	// particleSystem3
	NodePtr particleSystem3 = createParticleSystem();
	setName(particleSystem3, "particleSystem3");
	NodePtr particleSystem3Trans = Node::create();
	TransformPtr tparticleSystem3 = Transform::create();
	
	beginEditCP(tparticleSystem3);
	m.setIdentity();
	m.setTranslate(4.5, 48, 200);
	tparticleSystem3->setMatrix(m);
	endEditCP(tparticleSystem3);
    
	beginEditCP(particleSystem3Trans);
	particleSystem3Trans->setCore(tparticleSystem3);
	particleSystem3Trans->addChild(particleSystem3);
	endEditCP(particleSystem3Trans);
    
// ****
#endif

	
	// *********** Eingang ***********
	NodePtr entrance = createEntrance();
	
	// Transformation
	TransformPtr tentrance = Transform::create();
	beginEditCP(tentrance, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(2500/2-70/2, 100, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100);
	tentrance->setMatrix(m);
	endEditCP(tentrance, Transform::MatrixFieldMask);
	
	NodePtr entranceTrans = Node::create();
	beginEditCP(entranceTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	entranceTrans->setCore(tentrance);
	entranceTrans->addChild(entrance);
	endEditCP(entranceTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	// entranceStuff
	beginEditCP(entranceTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	entranceTrans->addChild(entranceObjectsTrans);
		
#ifdef PARTICLES_ON
	entranceTrans->addChild(particleSystem3Trans);
#endif
		
		// Add here entranceStuff..
	endEditCP(entranceTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	NodePtr roompassObjects = createRoompassObjects();
	
	// Transformation
	TransformPtr troompassObjects = Transform::create();
	beginEditCP(troompassObjects, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0, 0, 0);
	troompassObjects->setMatrix(m);
	endEditCP(troompassObjects, Transform::MatrixFieldMask);
		
	NodePtr roompassObjectsTrans = Node::create();
	beginEditCP(roompassObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	roompassObjectsTrans->setCore(troompassObjects);
	roompassObjectsTrans->addChild(roompassObjects);
	endEditCP(roompassObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	// *********** Raum durchgang ***********
	NodePtr roompass = createRoompass();
	
	// Transformation
	TransformPtr troompass = Transform::create();
	beginEditCP(troompass, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(2500/2-250/2-300, 100, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100-70/2);
	troompass->setMatrix(m);
	endEditCP(troompass, Transform::MatrixFieldMask);
	
	roompassTrans = Node::create();
	beginEditCP(roompassTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	roompassTrans->setCore(troompass);
	roompassTrans->addChild(roompass);
	endEditCP(roompassTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	// roompassStuff
	beginEditCP(roompass, Node::ChildrenFieldMask);
	roompass->addChild(roompassObjects);
		// Add here roompassStuff..
	endEditCP(roompass, Node::ChildrenFieldMask);


	NodePtr room1Objects = createRoom1Objects();
	
	// Transformation
	TransformPtr troom1Objects = Transform::create();
	beginEditCP(troom1Objects, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0, 0, 0);
	troom1Objects->setMatrix(m);
	endEditCP(troom1Objects, Transform::MatrixFieldMask);
		
	NodePtr room1ObjectsTrans = Node::create();
	beginEditCP(room1ObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	room1ObjectsTrans->setCore(troom1Objects);
	room1ObjectsTrans->addChild(room1Objects);
	endEditCP(room1ObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	

	// *********** Room 1 ***********
	NodePtr room1 = createRoom1();
	setName(room1,"room1");
		
	// Transformation
	TransformPtr troom1 = Transform::create();
	beginEditCP(troom1, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(2500/2-250/2, 100, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400);
	troom1->setMatrix(m);
	endEditCP(troom1, Transform::MatrixFieldMask);
		
	NodePtr room1Trans = Node::create();
	beginEditCP(room1Trans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	room1Trans->setCore(troom1);
	room1Trans->addChild(room1);
	endEditCP(room1Trans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	// room1Stuff
	beginEditCP(room1, Node::ChildrenFieldMask);
		// Add here room1Stuff..
	room1->addChild(simpleDoorTrans);
	room1->addChild(simpleDoorMarker);
	room1->addChild(room1ObjectsTrans);

#ifdef PARTICLES_ON
	room1->addChild(particleSystem1Trans);
	room1->addChild(particleSystem2Trans);
#endif
	
	endEditCP(room1, Node::ChildrenFieldMask);
	
	
	
	NodePtr room2Objects = createRoom2Objects();
	
	// Transformation
	TransformPtr troom2Objects = Transform::create();
	beginEditCP(troom2Objects, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(0, 0, 0);
	troom2Objects->setMatrix(m);
	endEditCP(troom2Objects, Transform::MatrixFieldMask);
		
	NodePtr room2ObjectsTrans = Node::create();
	beginEditCP(room2ObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	room2ObjectsTrans->setCore(troom2Objects);
	room2ObjectsTrans->addChild(room2Objects);
	endEditCP(room2ObjectsTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	// *********** Room 2 ***********
	NodePtr room2 = createRoom2();
		
	// Transformation
	TransformPtr troom2 = Transform::create();
	beginEditCP(troom2, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setRotate(Quaternion(Vec3f(0,1,0), M_PI/2));
	m.setTranslate(2500/2-250/2-300-300, 100, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100+250/2);
	troom2->setMatrix(m);
	endEditCP(troom2, Transform::MatrixFieldMask);
		
	NodePtr room2Trans = Node::create();
	beginEditCP(room2Trans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	room2Trans->setCore(troom2);
	room2Trans->addChild(room2);
	endEditCP(room2Trans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	// room2Stuff
	beginEditCP(room2, Node::ChildrenFieldMask);
	room2->addChild(room2ObjectsTrans);
		// Add here room2Stuff..
	endEditCP(room2, Node::ChildrenFieldMask);
	
	
	// *********** Pyramide ***********
	NodePtr pyra = createPyramid();

	// Transformation
	TransformPtr tpyra = Transform::create();
	beginEditCP(tpyra, Transform::MatrixFieldMask);
	m.setIdentity();
		//m.setTranslate(-2100, 0, -1900);
	tpyra->setMatrix(m);
	endEditCP(tpyra, Transform::MatrixFieldMask);
	
	NodePtr pyraTrans = Node::create();
	beginEditCP(pyraTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	pyraTrans->setCore(tpyra);
	pyraTrans->addChild(pyra);
	endEditCP(pyraTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	
	/***** Light Section START *****/
	
    //we add a little sphere that will represent the light source FOR TESTING
	GeometryPtr sphere = makeSphereGeo(2,2);

	SimpleMaterialPtr sm = SimpleMaterial::create();

	beginEditCP(sm, SimpleMaterial::DiffuseFieldMask |
			SimpleMaterial::LitFieldMask);
	{
		sm->setLit(false);
		sm->setDiffuse(Color3f(1,0,0));		// red ball
	}
	endEditCP  (sm, SimpleMaterial::DiffuseFieldMask |
			SimpleMaterial::LitFieldMask);

	beginEditCP(sphere, Geometry::MaterialFieldMask);
	{
		sphere->setMaterial(sm);
	}
	endEditCP  (sphere, Geometry::MaterialFieldMask);
    
	NodePtr sphereNode = Node::create();
	beginEditCP(sphereNode);
	sphereNode->setCore(sphere);
	endEditCP(sphereNode);
    
	
    // *********** cryptLight1 ***********
	NodePtr cryptLight1Trans = Node::create();
	setName(cryptLight1Trans, "cryptLight1Trans");
	NodePtr cryptLight1 = createFireLight( cryptLight1Trans, room1Trans);
	setName(cryptLight1,"cryptLight1");
    
	TransformPtr tcryptLight1 = Transform::create();
	beginEditCP(tcryptLight1);
	m.setIdentity();
	m.setTranslate((2500/2-250/2)+5, 100+52, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+160);
	tcryptLight1->setMatrix(m);
	endEditCP(tcryptLight1);
    
	beginEditCP(cryptLight1Trans);
	cryptLight1Trans->setCore(tcryptLight1);
	cryptLight1Trans->addChild(cryptLight1);    
	endEditCP(cryptLight1Trans);
   
	NodePtr nLightTmp;
	PointLightPtr pLight;
#ifndef CRYPT_LIGHT1_ON   
	nLightTmp = getNamedNode(cryptLight1Trans,"cryptLight1");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif

	// *********** cryptLight2 ***********
	NodePtr cryptLight2Trans = Node::create();
	setName(cryptLight2Trans, "cryptLight2Trans");
	NodePtr cryptLight2 = createFireLight( cryptLight2Trans, cryptLight1);
	setName(cryptLight2,"cryptLight2");
    
	TransformPtr tcryptLight2 = Transform::create();
	beginEditCP(tcryptLight2);
	m.setIdentity();
	m.setTranslate((2500/2-250/2)+245, 100+52, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+160);
	tcryptLight2->setMatrix(m);
	endEditCP(tcryptLight2);
    
	beginEditCP(cryptLight2Trans);
	cryptLight2Trans->setCore(tcryptLight2);
	cryptLight2Trans->addChild(cryptLight2);  
	endEditCP(cryptLight2Trans);
   
#ifndef CRYPT_LIGHT2_ON   
	nLightTmp = getNamedNode(cryptLight2Trans,"cryptLight2");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif
    /*
	// *********** cryptLight3 ***********
	NodePtr cryptLight3Trans = Node::create();
	setName(cryptLight3Trans, "cryptLight3Trans");
	NodePtr cryptLight3 = createFireLight( cryptLight3Trans, cryptLight2);
	setName(cryptLight3,"cryptLight3");
    
	TransformPtr tcryptLight3 = Transform::create();
	beginEditCP(tcryptLight3);
	m.setIdentity();
	m.setTranslate((2500/2-250/2)+170, 100+52, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+395);
	tcryptLight3->setMatrix(m);
	endEditCP(tcryptLight3);
    
	beginEditCP(cryptLight3Trans);
	cryptLight3Trans->setCore(tcryptLight3);
	cryptLight3Trans->addChild(cryptLight3);  
	endEditCP(cryptLight3Trans);
   
#ifndef CRYPT_LIGHT3_ON   
	nLightTmp = getNamedNode(cryptLight3Trans,"cryptLight3");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif
    */
    /*	
	// *********** cryptLight4 ***********
	NodePtr cryptLight4Trans = Node::create();
	setName(cryptLight4Trans, "cryptLight4Trans");
	NodePtr cryptLight4 = createFireLight( cryptLight4Trans, cryptLight3);
	setName(cryptLight4,"cryptLight4");
    
	TransformPtr tcryptLight4 = Transform::create();
	beginEditCP(tcryptLight4);
	m.setIdentity();
	m.setTranslate((2500/2-250/2)+80, 100+52, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+395);
	tcryptLight4->setMatrix(m);
	endEditCP(tcryptLight4);
    
	beginEditCP(cryptLight4Trans);
	cryptLight4Trans->setCore(tcryptLight4);
	cryptLight4Trans->addChild(cryptLight4);  
	endEditCP(cryptLight4Trans);
   
#ifndef CRYPT_LIGHT4_ON   
	nLightTmp = getNamedNode(cryptLight4Trans,"cryptLight4");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	
    */
    
    // *********** entranceLight1 ***********
	NodePtr entranceLight1Trans = Node::create();
	setName(entranceLight1Trans, "entranceLight1Trans");
	NodePtr entranceLight1 = createFireLight( entranceLight1Trans, entranceTrans);
	setName(entranceLight1,"entranceLight1");
    
	TransformPtr tentranceLight1 = Transform::create();
	beginEditCP(tentranceLight1);
	m.setIdentity();
	m.setTranslate(2500/2-70/2 + 5, 100 + 52, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100 + 200);
	tentranceLight1->setMatrix(m);
	endEditCP(tentranceLight1);
    
	beginEditCP(entranceLight1Trans);
	entranceLight1Trans->setCore(tentranceLight1);
	entranceLight1Trans->addChild(entranceLight1);
	endEditCP(entranceLight1Trans);
   
#ifndef ENTRANCE_LIGHT1_ON   
	nLightTmp = getNamedNode(entranceLight1Trans,"entranceLight1");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	
	
	/*
	// *********** entranceLight2 ***********
	NodePtr entranceLight2Trans = Node::create();
	setName(entranceLight2Trans, "entranceLight2Trans");
	NodePtr entranceLight2 = createFireLight( entranceLight2Trans, entranceLight1);
	setName(entranceLight2,"entranceLight2");
    
	TransformPtr tentranceLight2 = Transform::create();
	beginEditCP(tentranceLight2);
	m.setIdentity();
	m.setTranslate(2500/2-70/2 + 65, 100 + 52, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100 + 400);
	tentranceLight2->setMatrix(m);
	endEditCP(tentranceLight2);
    
	beginEditCP(entranceLight2Trans);
	entranceLight2Trans->setCore(tentranceLight2);
	entranceLight2Trans->addChild(entranceLight2);
	endEditCP(entranceLight2Trans);
   
#ifndef ENTRANCE_LIGHT2_ON   
	nLightTmp = getNamedNode(entranceLight2Trans,"entranceLight2");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	
	*/
    
	/*
	// *********** roompassLight1 ***********
	NodePtr roompassLight1Trans = Node::create();
	setName(roompassLight1Trans, "roompassLight1Trans");
	NodePtr roompassLight1 = createFireLight( roompassLight1Trans, roompassTrans);
	setName(roompassLight1,"roompassLight1");
    
	TransformPtr troompassLight1 = Transform::create();
	beginEditCP(troompassLight1);
	m.setIdentity();
	m.setTranslate(2500/2-250/2-300 + 150, 100 + 52, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100-70/2 + 65);
	troompassLight1->setMatrix(m);
	endEditCP(troompassLight1);
    
	beginEditCP(roompassLight1Trans);
	roompassLight1Trans->setCore(troompassLight1);
	roompassLight1Trans->addChild(roompassLight1);
	endEditCP(roompassLight1Trans);
   
#ifndef ROOMPASS_LIGHT1_ON   
	nLightTmp = getNamedNode(roompassLight1Trans,"roompassLight1");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif
	*/
	
	/*
	// *********** room2Light1 ***********
	NodePtr room2Light1Trans = Node::create();
	setName(room2Light1Trans, "room2Light1Trans");
	NodePtr room2Light1 = createFireLight( room2Light1Trans, room2Trans);
	setName(room2Light1,"room2Light1");
    
	TransformPtr troom2Light1 = Transform::create();
	beginEditCP(troom2Light1);
	m.setIdentity();
	m.setTranslate(2500/2-250/2-300-300 + 150, 100 + 52, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100+250/2 - 5);
	troom2Light1->setMatrix(m);
	endEditCP(troom2Light1);
    
	beginEditCP(room2Light1Trans);
	room2Light1Trans->setCore(troom2Light1);
	room2Light1Trans->addChild(room2Light1);
	endEditCP(room2Light1Trans);
   
#ifndef ROOM2_LIGHT1_ON   
	nLightTmp = getNamedNode(room2Light1Trans,"room2Light1");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	
    
	// *********** room2Light2 ***********
	NodePtr room2Light2Trans = Node::create();
	setName(room2Light2Trans, "room2Light2Trans");
	NodePtr room2Light2 = createFireLight( room2Light2Trans, room2Light1);
	setName(room2Light2,"room2Light2");
    
	TransformPtr troom2Light2 = Transform::create();
	beginEditCP(troom2Light2);
	m.setIdentity();
	m.setTranslate(2500/2-250/2-300-300 + 150, 100 + 52, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100+250/2 - 245);
	troom2Light2->setMatrix(m);
	endEditCP(troom2Light2);
    
	beginEditCP(room2Light2Trans);
	room2Light2Trans->setCore(troom2Light2);
	room2Light2Trans->addChild(room2Light2);
	endEditCP(room2Light2Trans);
   
#ifndef ROOM2_LIGHT2_ON   
	nLightTmp = getNamedNode(room2Light2Trans,"room2Light2");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	
	*/
	
	/*
	NodePtr groupNode = Node::create();
	beginEditCP(groupNode, Node::CoreFieldMask | Node::ChildrenFieldMask);
	groupNode->setCore(Group::create());
	groupNode->addChild(room2Trans);
	groupNode->addChild(roompassTrans);
	endEditCP(groupNode, Node::CoreFieldMask | Node::ChildrenFieldMask);	
	*/
	
	// *********** room2BlueLight1 ***********
	NodePtr room2BlueLight1Trans = Node::create();
	setName(room2BlueLight1Trans, "room2BlueLight1Trans");
	NodePtr room2BlueLight1 = createBlueLight( room2BlueLight1Trans, room2Trans);
	setName(room2BlueLight1,"room2BlueLight1");
    
	TransformPtr troom2BlueLight1 = Transform::create();
	beginEditCP(troom2BlueLight1);
	m.setIdentity();
	m.setTranslate(2500/2-250/2-300-300 + 95, 100 + 50, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100+250/2 - 130);
	troom2BlueLight1->setMatrix(m);
	endEditCP(troom2BlueLight1);
    
	beginEditCP(room2BlueLight1Trans);
	room2BlueLight1Trans->setCore(troom2BlueLight1);
	room2BlueLight1Trans->addChild(room2BlueLight1);
	//room2BlueLight1Trans->addChild(sphereNode);
	endEditCP(room2BlueLight1Trans);
    
	beginEditCP(room2BlueLight1);
	room2BlueLight1->addChild(roompassTrans);
	endEditCP(room2BlueLight1);
    
#ifndef ROOM2_BLUELIGHT1_ON  
	nLightTmp = getNamedNode(room2BlueLight1Trans,"room2BlueLight1");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	
	
	// *********** sunLight1 ***********
	NodePtr sunLight1Trans = Node::create();
	setName(sunLight1Trans, "sunLight1Trans");
	NodePtr sunLight1 = createSunLight( sunLight1Trans, pyraTrans);
	setName(sunLight1,"sunLight1");
    
	TransformPtr tsunLight1 = Transform::create();
	beginEditCP(tsunLight1);
	m.setIdentity();
	m.setTranslate(2500, 1000, 3500);
	tsunLight1->setMatrix(m);
	endEditCP(tsunLight1);
    
	beginEditCP(sunLight1Trans);
	sunLight1Trans->setCore(tsunLight1);
	sunLight1Trans->addChild(sunLight1);
	endEditCP(sunLight1Trans);
       
#ifndef SUNLIGHT1_ON
	nLightTmp = getNamedNode(sunLight1Trans,"sunLight1");
	pLight = PointLightPtr::dcast(nLightTmp->getCore());
	pLight->setOn(false);
#endif	

	/***** Light Section END *****/
   
    
	NodePtr terrain = createTerrain();
	setName(terrain,"terrain");
    
    // pyraStuff
	beginEditCP(pyra, Node::ChildrenFieldMask);		
		// Add here pyraStuff..
		
		pyra->addChild(terrain);
	endEditCP(pyra, Node::ChildrenFieldMask);
	

    	
	
// This is our scenegraph root node
	NodePtr n = Node::create();
	beginEditCP(n, Node::CoreFieldMask | Node::ChildrenFieldMask);
	n->setCore(Group::create());
	n->addChild(sunLight1);			// sunlight1 (sunLight1 -> pyraTrans )
	n->addChild(sunLight1Trans);		// Beacon sunLight1Trans
		
	n->addChild(cryptLight2);			// Light2 (light2 -> light1 -> room1Trans )
	n->addChild(cryptLight2Trans);		// Beacon cryptLight2
	n->addChild(cryptLight1Trans); 	// Beacon cryptLight1
		
	n->addChild(entranceLight1);		// entranceLight1 ( entranceLight1 -> entranceTrans )
		//n->addChild(entranceLight2Trans);	// Beacon entranceLight2
	n->addChild(entranceLight1Trans);	// Beacon entranceLight1 
		
		//n->addChild(roompassLight1);		// roompassLight1 (roompassLight1 -> roompassTrans);
		//n->addChild(roompassLight1Trans);	// Beacon roompassLight1Trans
		
	n->addChild(room2BlueLight1);		// room2BlueLight1 ( room2BlueLight1 -> room2Trans )
											//                 ( room2BlueLight1 -> roompassTrans )
	n->addChild(room2BlueLight1Trans);	// Beacon room2BlueLight1Trans
	endEditCP(n, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	return n;
	
}

void reshape(int w, int h)
{
	mgr->resize(w, h);
	glutPostRedisplay();
}

// helper function for updating the stargate iris mesh

void updateMesh(Real32 time){

	Matrix m;

	double morphx;

	if (stargate_evolving){
		evolution_counter+=1.5;
	//cout << "DEBUG: stargate evolution:" << evolution_counter << endl;
		for (int ring = 0; ring <= 20; ring++)
			for (int position = 0; position < 36; position++)
				iris_mesh[ring][position] = abs(sin(time/1000.f+ring)*3*(20-ring)*sin(DEG2RAD(evolution_counter)));
	//cout << "DEBUG: evolution depth: " << iris_mesh[ring][position] << endl;

		NodePtr animationNode = getNamedNode(scene,"room2BlueLight1Trans");
	
		morphx = 100 * sin (DEG2RAD(evolution_counter));

		m.setIdentity();
		m.setTranslate(2500/2-250/2-300-300 + 95 + morphx, 100 + 50, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400/2+100+250/2 - 130);
		//m.setTranslate((2500/2-250/2)+245+morphx, 100+52+morphy, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+160+morphz);
	
		TransformPtr anim = TransformPtr::dcast(animationNode->getCore());
	
		beginEditCP(anim);
		anim->setMatrix(m);
		endEditCP(anim);

		if (evolution_counter>=180) stargate_evolving=false;
	}
	else
	{
		for (int ring = 0; ring <= 20; ring++)
			for (int position = 0; position < 36; position++)
            //iris_mesh[ring][position] = 1*sin(time/1000.f+2*ring);
				iris_mesh[ring][position] = 1*sin(time/1000.f+2*ring);
	}
}

void display(void)
{

// animate stargate iris

	Real32 time = glutGet(GLUT_ELAPSED_TIME);
	updateMesh(time);

	GeometryPtr geo_mod = GeometryPtr::dcast(getNamedNode(scene,"stargate_iris")->getCore());
	calcVertexNormals(geo_mod); 
	GeoPositions3fPtr pos_mod = GeoPositions3fPtr::dcast(geo_mod->getPositions());

	beginEditCP(pos_mod, GeoPositions3f::GeoPropDataFieldMask);
	int i=0;
	for (int ring = 0; ring <= 20; ring+=1)
	{
		for (int position = 0; position < 360; position+=10)
		{
			pos_mod->setValue(Pnt3f(2*ring*cos(deg2rad(position)), 2*ring*sin(deg2rad(position)) , 2*iris_mesh[ring][position/10]),i);
			i++;
		}
	}
	endEditCP(pos_mod, GeoPositions3f::GeoPropDataFieldMask);


#ifdef LIGHT_ANIMATION_ON
	double morphx,morphy,morphz;
    
	brake++;
	if (brake==BRAKEVALUE){
		brake=0;
		
	
		NodePtr animationNode = getNamedNode(scene,"cryptLight1Trans");
	
		Matrix m;
	
		// increase oscillation
		osc+=1;

		if (osc>=360) osc-=360;

		morphx = 0;
		morphy = 3 * sin(DEG2RAD(osc));
		morphz = 6 * sin(DEG2RAD(osc));

		m.setIdentity();		
		m.setTranslate((2500/2-250/2)+5 +morphx, 100+52+morphy, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+160+morphz);
	
		TransformPtr anim = TransformPtr::dcast(animationNode->getCore());
		
		beginEditCP(anim);
		anim->setMatrix(m);
		endEditCP(anim);
		
		animationNode = getNamedNode(scene,"cryptLight2Trans");
	
		morphx = 0;
		morphy = 4 * sin(DEG2RAD(osc));
		morphz = -6 * sin(DEG2RAD(osc)) + cos(DEG2RAD(osc));
	
		m.setIdentity();
		m.setTranslate((2500/2-250/2)+245+morphx, 100+52+morphy, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+160+morphz);
	
		anim = TransformPtr::dcast(animationNode->getCore());
	
		beginEditCP(anim);
		anim->setMatrix(m);
		endEditCP(anim);

		animationNode = getNamedNode(scene,"entranceLight1Trans");
	
		morphx = 0;
		morphy = 4 * sin(DEG2RAD(osc));
		morphz = 6 * sin(DEG2RAD(osc)) + cos(DEG2RAD(osc));
	
		m.setIdentity();
		m.setTranslate(2500/2-70/2 + 5 + morphx, 100 + 52+morphy, 2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100 + 200+morphz);

		//m.setTranslate((2500/2-250/2)+245+morphx, 100+52+morphy, (2500-600-tan(M_PI/2-atan(2500/(2500/2)))*100-400)+160+morphz);
	
		anim = TransformPtr::dcast(animationNode->getCore());
	
		beginEditCP(anim);
		anim->setMatrix(m);
		endEditCP(anim);

	}
#endif

		// door animation

	if (doormoving){
		
		if (!dooropen){

			doorposition+=1;

			if (doorposition==90) {
		
				dooropen=true;
				doormoving=false;
			}
		}
		else
			doorposition-=1;

		if (doorposition==0) {
		
			dooropen=false;
			doormoving=false;
		}

		Matrix m;

		NodePtr DoorTrans = getNamedNode(scene,"simpleDoorTrans");
		
		m.setIdentity();
		//m.setTranslate(20,50+doorposition,350);
		m.setTranslate(-4,45+doorposition,300);
		m.setRotate(Quaternion(Vec3f(0,1,0), -3.14159/2));

		TransformPtr anim = TransformPtr::dcast(DoorTrans->getCore());
	
		beginEditCP(anim);
			//anim->getMatrix().setTranslate(0.0, doorposition, 0.0);
		anim->setMatrix(m);
		endEditCP(anim);

	}
	

		

#ifdef PARTICLES_ANIMATION_ON
		
	// get particlesptr
	ParticlesPtr pParticleSystem1 = ParticlesPtr::dcast(getNamedNode(scene,"particleSystem1")->getCore());	
	ParticlesPtr pParticleSystem2 = ParticlesPtr::dcast(getNamedNode(scene,"particleSystem2")->getCore());	
	ParticlesPtr pParticleSystem3 = ParticlesPtr::dcast(getNamedNode(scene,"particleSystem3")->getCore());	
	
	// create tmp-variables and get fields
	GeoPositions3fPtr tmpPnts = GeoPositions3f::create();
	MFPnt3f *tmpfieldPtr = tmpPnts->getFieldPtr();
	MFPnt3f *fieldPtr = pnts->getFieldPtr();	
	tmpColors = GeoColors3f::create();
	
	morphx = 0;
	morphy = 3 * sin(DEG2RAD(osc));
	morphz = 6 * sin(DEG2RAD(osc));
	
	// emitter-parameters
	double fireLevel = 4.3;					// 4.3
	// set some range parameters
	double startPointXRange = 1.7;		// 1.7
	double startPointYRange = 0.80;		// 0.80
	double startPointZRange = 1.7;		// 1.7
	double targetPointXRange = 0.15; 		// 0.15
	double targetPointYRange = 1.0;	 	// 1.0
	double targetPointZRange = 0.15; 		// 0.15
	int emitNum = 50; // number of particles to create 50
	double lifeSpanTicket = 0.02; 			// 0.02
	double lifeSpanMax = 1.0;
	
	// create some 3d-vectors
	Vec3d startPointVec3d, targetVec3d, targetPointVec3d;
	Vec3d deltaVec3d, tmpStartPointVec3d, tmpTargetVec3d;

	// get iterators of the vector-lists
	vector<double>::iterator lifeSpanListIterator;
	vector<Vec3d>::iterator startVec3dListIterator;
	vector<Vec3d>::iterator targetVec3dListIterator;
	
	// initialize iterators
	lifeSpanListIterator = lifeSpanList.begin();
	startVec3dListIterator = startVec3dList.begin();
	targetVec3dListIterator = targetVec3dList.begin();
	
	// clear all colors to recreate them later
	cols->getFieldPtr();
	cols->clear();
	
	//printf("particle-count = %d\n", fieldPtr->size());
	
	// manage old particles
	for(UInt32 i=0; i < fieldPtr->size(); ++i)
	{
		// calc if particle is dead
		if(*lifeSpanListIterator > lifeSpanMax)
		{
			// delete dead particle from all vector-lists
			lifeSpanList.erase(lifeSpanListIterator);
			startVec3dList.erase(startVec3dListIterator);
			targetVec3dList.erase(targetVec3dListIterator);
		}else // else calc new position, new color + save data
		{
			// get old position
			Pnt3f pos=(*fieldPtr)[i];
	        
	        // calc deltaVector (lifeSpan * targetVec)
			tmpTargetVec3d = *targetVec3dListIterator;
			deltaVec3d[0] = *lifeSpanListIterator * tmpTargetVec3d[0];
			deltaVec3d[1] = *lifeSpanListIterator * tmpTargetVec3d[1];
			deltaVec3d[2] = *lifeSpanListIterator * tmpTargetVec3d[2];
	        
	        // calc new position (startPointVec + deltaVec)
			tmpStartPointVec3d = *startVec3dListIterator;
			pos[0] = tmpStartPointVec3d[0] + deltaVec3d[0];
			pos[1] = tmpStartPointVec3d[1] + deltaVec3d[1];
			pos[2] = tmpStartPointVec3d[2] + deltaVec3d[2];
	       
	        // write new position to tmpfield
			tmpfieldPtr->push_back(pos);
	        
	        // calc new colors
			int red 	= 255 - *lifeSpanListIterator * 250 + dRand(60);
			int green 	= 255 - *lifeSpanListIterator * 500 + dRand(60);
			int blue 	= 155 - *lifeSpanListIterator * 4000;
	        	        
	        // write new color to tmpfield
			tmpColors->push_back( Color3f(red, green, blue) );
	      
	        // increment lifetime
			*lifeSpanListIterator += lifeSpanTicket;
	        
			lifeSpanListIterator++; 
			startVec3dListIterator++;
			targetVec3dListIterator++;		
		}	
	}
	// cut vectors to really size
	lifeSpanList.resize(tmpfieldPtr->size());
	startVec3dList.resize(tmpfieldPtr->size());
	targetVec3dList.resize(tmpfieldPtr->size());	
	
	
	// create new particles
	for(int i=0; i < emitNum; ++i)
	{
		// calc startPointVector
		startPointVec3d[0] = dRand(startPointXRange);
		startPointVec3d[1] = dRand(startPointYRange);
		startPointVec3d[2] = dRand(startPointZRange);

       	// calc targetPointVector
		targetPointVec3d[0] = dRand(targetPointXRange) + morphz/9;
		targetPointVec3d[1] = dRand(targetPointYRange) + fireLevel;
		targetPointVec3d[2] = dRand(targetPointZRange) + morphz/9;
        
        // create 1 particle at position(x,y,z)
		tmpfieldPtr->push_back(startPointVec3d);	
       
        // set start color
		tmpColors->push_back( Color3f(	255, 255, 155) );	
    	
        //size->push_back( Vec3f(0.3, 0, 0) ); // no need to set, default is (1,1,1)
        
        // save lifespan for the new particle
		lifeSpanList.push_back(0.0);
        
        // save startVec for the new particle
		startVec3dList.push_back(startPointVec3d);	
        
        // calc targetVec
		targetVec3d[0] = targetPointVec3d[0] - startPointVec3d[0];
		targetVec3d[1] = targetPointVec3d[1] - startPointVec3d[1];
		targetVec3d[2] = targetPointVec3d[2] - startPointVec3d[2];
        // save targetVec for the new particle
		targetVec3dList.push_back(targetVec3d);		
	}
    
	// swap from tmp-variable to really used variable
	std::swap(pnts, tmpPnts);
	std::swap(cols, tmpColors);
    // set the date for the particle-systems
	pParticleSystem1->setPositions(pnts);
	pParticleSystem1->setColors(cols);
	pParticleSystem2->setPositions(pnts);
	pParticleSystem2->setColors(cols);
	pParticleSystem3->setPositions(pnts);
	pParticleSystem3->setColors(cols);
	
#endif
		
		
	
	mgr->idle();
	mgr->redraw();
}

void mouse(int button, int state, int x, int y)
{
	if (state)
		mgr->mouseButtonRelease(button, x, y);
	else
		mgr->mouseButtonPress(button, x, y);
	glutPostRedisplay();
}

void motion(int x, int y)
{
	mgr->mouseMove(x, y);
	mousex=x;
	mousey=y;
	glutPostRedisplay();
}

void passivemotion(int x, int y)
{
	// check if mouse is over clickable object

	Line ray = mgr->calcViewRay(x, y);
	NodePtr ISectNode = getNamedNode(scene,"cryptLight1");

	NodePtr DoorMarker = getNamedNode(scene,"simpleDoorMarker");
	
	IntersectAction *iAct = IntersectAction::create();
	iAct->setLine(ray);
	iAct->apply(ISectNode);
        //see if anything was hit
	if (iAct->didHit())
	{
            // get the hit point
		Pnt3f p = iAct->getHitPoint();
		//cout << "Hit point : " << p[0] << " " << p[1] << " " << p[2] << endl;
            //and the node that was hit
		NodePtr clickedObject = iAct->getHitObject();
		if (getName(clickedObject)){
			std::string name = getName(clickedObject);
			if (name=="simpleDoor"){
				//cout << "simpleDoor hovered" << endl;
				door_hover=true;
			}
			else
			{
				//cout << "simpleDoor unhovered" << endl;
				door_hover=false;
			}
			if (name=="simpleDoorTrans"){
				//cout << "coffin hovered" << endl;
				coffin_hover=true;
			}
			else
			{		
				//cout << "coffin unhovered" << endl;
				coffin_hover=false;
			}
		}
		else
		{
			//cout << "simpleDoor unhovered" << endl;
			door_hover=false;
			coffin_hover=false;
		}
	}
	
	if (door_hover)
	{
		beginEditCP(DoorMarker);	
		DoorMarker->setActive(true);
		endEditCP(DoorMarker);
	}
	else
	{
		beginEditCP(DoorMarker);	
		DoorMarker->setActive(false);
		endEditCP(DoorMarker);
	}
	
	if (coffin_hover)
	{
		//do something to highlight coffin
	}

	mousex=x;
	mousey=y;
}

// keyboard callback
void keyboard(unsigned char k, int x, int y)
{
	switch(k)
	{
		case ' ':
		{
			if (door_hover){
				//cout << "simpleDoor clicked" << endl;
				FSOUND_PlaySound(3,door_movement);
				doormoving=true;
			}
		}
		break;

		case 27:    
		{
			OSG::osgExit();
			exit(0);
		}
		break;

		case '1':
			mgr->setNavigationMode(Navigator::FLY);
			mgr->getNavigator()->setUp(Vec3f(0,1,0));
			break;

		case '2':
			mgr->setNavigationMode(Navigator::TRACKBALL);
			break;

		case '3':
		{
			mgr->setNavigationMode(Navigator::WALK);
			mgr->getNavigator()->getWalkNavigator()->setGroundDistance(1);
			mgr->getNavigator()->getWalkNavigator()->setMinWallDistance(10);
			mgr->getNavigator()->getWalkNavigator()->setPersonDimensions(50,20,20);
			mgr->getNavigator()->getWalkNavigator()->setUp(Vec3f(0,1,0));
			mgr->getNavigator()->getWalkNavigator()->setWorld(walker_scene);
			mgr->getNavigator()->getWalkNavigator()->setGround(walker_scene);
		}	
		break;

		case 'x':
			mgr->getNavigator()->set(Pnt3f(1250,150,2800),Pnt3f(1250,150,0),Vec3f(0,1,0));
			break;

		case '-':
			speed *= .9;
			mgr->getNavigator()->setMotionFactor(speed);
			break;

		case '+':
			speed *= 1.1;
			mgr->getNavigator()->setMotionFactor(speed);
			break;
	
		case 'c':
		{
			RenderAction *ract = (RenderAction *) mgr->getAction();
			ract->setOcclusionCulling(!ract->getOcclusionCulling());
		}
		break;
		case 'v':
		{
			RenderAction *ract = (RenderAction *) mgr->getAction();
			ract->setOcclusionCullingMode(RenderAction::OcclusionStopAndWait);
		}
		break;
		case 'b':
		{
			RenderAction *ract = (RenderAction *) mgr->getAction();
			ract->setOcclusionCullingMode(RenderAction::OcclusionMultiFrame);
			mgr->redraw();
		}
		break;
		case 'n':
		{
			RenderAction *ract = (RenderAction *) mgr->getAction();
			ract->setOcclusionCullingMode(RenderAction::OcclusionHierarchicalMultiFrame);
			mgr->redraw();
		}
		break;
		case 't':
		{
			cout << endl << endl;
			cout << "Printing all node names";
			cout << "---------------------------------------";
			cout << endl << endl;
			traverse(scene, osgTypedFunctionFunctor1CPtrRef<Action::ResultE, NodePtr>(enter));
		}
		break;
		case 'e':
		{
			// export the whole scene
			SceneFileHandler::the().write(scene, "scene_output.bin");
			printf("Exported the whole Scene to scene_output.bin\n");
		}
		break;
		case 'p':
		{
			cout << "DEBUG: Position: " << mgr->getNavigator()->getAt();
		}
		break;
		//trigger sample file
		case 'l':    FSOUND_PlaySound(2,tardis_landing);
		break;
		case 's':
		{
			FSOUND_PlaySound(3,gate_opening);
			evolution_counter=0;
			stargate_evolving=true;
		}
		break;
		case 'w':
		{
		shadows_on=!shadows_on;
		if (shadows_on)
			svp->setShadowMode(ShadowViewport::PCF_SHADOW_MAP);
		else
			svp->setShadowMode(ShadowViewport::NO_SHADOW);
		}
		break;
	}
	mgr->key(k,x,y);
	glutPostRedisplay();
}

int setupGLUT(int *argc, char *argv[])
{
	glutInit(argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
	//glutInitWindowSize(800,600);
	glutInitWindowSize(1024,768);
	int windowID = glutCreateWindow("CG1 Project Wookies - Pyramid");
	
	glutDisplayFunc(display);
	glutIdleFunc(display);
	glutReshapeFunc(reshape);
	glutMouseFunc(mouse);
	glutMotionFunc(motion);
	glutPassiveMotionFunc(passivemotion);
	glutKeyboardFunc(keyboard);
	
	return windowID;
}

// calc a double random number within the range -n/2 to +n/2
double dRand(double range)
{
	range++;
	return ((double(rand())/RAND_MAX)*range)-range/2;
}

// global texture chunk creator for skybox textures
TextureChunkPtr createTexture( std::string filename ) {
	OSG::TextureChunkPtr tex = OSG::TextureChunk::create();
	OSG::ImagePtr img;

	OSG::beginEditCP(tex);
	tex->setMinFilter( GL_NEAREST );
	tex->setMagFilter( GL_NEAREST );
	tex->setWrapS    ( GL_CLAMP );
	tex->setWrapT    ( GL_CLAMP );
	tex->setWrapR    ( GL_CLAMP );
	tex->setEnvMode  ( GL_REPLACE );

	img = OSG::Image::create();
	img->read( filename.c_str() );
	tex->setImage(img);
	OSG::endEditCP(tex);

	return tex;
}

Action::ResultE enter(NodePtr& node)
{   
	if (getName(node))
	{
		cout << getName(node) << endl;
	}
	return Action::Continue;
}

NodePtr getNamedNode(NodePtr n, std::string name)
{
	UInt32 children = n->getNChildren();
	
	if (getName(n))
		if (getName(n)==name){
#ifdef DEBUG
		cout << "Named node found: " << name << endl;
#endif
		return n;
		}
		for (UInt32 i = 0; i < children; i++)
		{
			NodePtr r = getNamedNode(n->getChild(i),name);
			if (r != NullFC)
				return r;
		}
		return NullFC;
}
